package bma.common.netty.chunk;

import java.nio.channels.ClosedChannelException;

import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.DefaultChannelFuture;

public class ChunkedContentChannelWriter implements ChannelFutureListener {

	private Channel channel;
	private ChunkedContentProvider provider;
	private ChannelFutureListener listener;

	public Channel getChannel() {
		return channel;
	}

	public ChunkedContentProvider getProvider() {
		return provider;
	}

	public ChannelFutureListener getListener() {
		return listener;
	}

	public void write(Channel channel, ChunkedContentProvider provider,
			ChannelFutureListener lis) throws Exception {
		if (channel == null)
			throw new NullPointerException("channel");
		if (provider == null)
			throw new NullPointerException("chunked content provider");

		this.channel = channel;
		this.provider = provider;
		this.listener = lis;

		processNext();
	}

	protected void processNext() throws Exception {
		Object obj = provider.nextContent();
		if (obj == null) {
			if (this.listener != null) {
				DefaultChannelFuture f = new DefaultChannelFuture(channel,
						false);
				f.setSuccess();
				this.listener.operationComplete(f);
			}
			return;
		}
		if (channel.isOpen()) {
			channel.write(obj).addListener(this);
		} else {
			if (this.listener != null) {
				DefaultChannelFuture f = new DefaultChannelFuture(channel,
						false);
				f.setFailure(new ClosedChannelException());
				this.listener.operationComplete(f);
			}
		}
	}

	@Override
	public void operationComplete(ChannelFuture future) throws Exception {
		if (future.isCancelled() || !future.isSuccess()) {
			if (this.listener != null) {
				this.listener.operationComplete(future);
			}
			return;
		}
		processNext();
	}

}
